package com.huxi.lang.file.xls;

import java.time.ZoneOffset;
import java.util.Objects;
import java.util.stream.Stream;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 表格页封装
 */
public class TableSheet {

	private Sheet sheet;
	private ZoneOffset offset;

	public TableSheet(Sheet sheet, ZoneOffset offset) {
		this.sheet = Objects.requireNonNull(sheet);
		this.offset = Objects.requireNonNull(offset);
	}

	public Sheet getSheet() {
		return sheet;
	}

	public void setSheet(Sheet sheet) {
		this.sheet = Objects.requireNonNull(sheet);
	}

	public void addEmptyRow(int count) {
		int rownum = sheet.getLastRowNum() + 1;
		for (int ii = 0; ii < count; ii++) {
			sheet.createRow(rownum);
			rownum++;
		}
	}

	public void insertEmptyRow(int index, int count) {
		if (index < sheet.getFirstRowNum()) {
			index = sheet.getFirstRowNum();
		} else if (index > sheet.getLastRowNum()) {
			index = sheet.getLastRowNum() + 1;
		}
		// TODO
	}

	/**
	 * 是否.XLSX文件格式
	 * 
	 * @return XLSX文件格式返回真，否则返回假。
	 */
	public boolean isXSSF() {
		return sheet.getWorkbook() instanceof XSSFWorkbook;
	}

	/**
	 * 创建工作表格原始行封装
	 * 
	 * @param row 原始表格行，非空值。
	 * @return 封装后表格行
	 */
	private TableRow createTableRow(Row row) {
		return new TableRow(row, offset);
	}

	/**
	 * 表格行记录数量
	 * 
	 * @return 行记录数量
	 */
	public int size() {
		return sheet.getLastRowNum() + 1;
	}

	/**
	 * 生成表格行记录流
	 * 
	 * @param rownum 起始行号，从0开始计数。
	 * @return 行记录流，非空值。
	 */
	public Stream<Row> rowsStream(int rownum) {
		if (rownum < sheet.getFirstRowNum()) {
			rownum = sheet.getFirstRowNum();
		}
		final int size = sheet.getLastRowNum();
		if (rownum >= 0 && rownum <= size) {
			Row first = sheet.getRow(rownum);
			if (first == null) {
				first = sheet.createRow(rownum);
			}
			return Stream.iterate(first, (item) -> {
				return item.getRowNum() <= size;
			}, (item) -> {
				if (size != sheet.getLastRowNum()) {
					throw new IllegalStateException("工作表格探测总行数已变更，行记录访问快速失败！");
				}
				int next = item.getRowNum() + 1;
				Row row = sheet.getRow(next);
				if (row == null) {
					row = sheet.createRow(next);
				}
				return row;
			});
		} else {
			return Stream.empty();
		}
	}

	/**
	 * 生成表格行记录流
	 * 
	 * @return 行记录流，非空值。
	 * @see #rowsStream(int)
	 */
	public Stream<Row> rowsStream() {
		return rowsStream(sheet.getFirstRowNum());
	}

	/**
	 * 生成表格包裹行记录流
	 * 
	 * @return 数据行流
	 */
	public Stream<TableRow> stream() {
		return stream(sheet.getFirstRowNum());
	}

	/**
	 * 生成表格包裹行记录流
	 * 
	 * @param rownum 起始行
	 * @return 数据行流
	 */
	public Stream<TableRow> stream(int rownum) {
		if (rownum < sheet.getFirstRowNum()) {
			rownum = sheet.getFirstRowNum();
		}
		final int size = sheet.getLastRowNum();
		if (rownum >= 0 && rownum <= size) {
			Row first = sheet.getRow(rownum);
			if (first == null) {
				first = sheet.createRow(rownum);
			}
			return Stream.iterate(createTableRow(first), (item) -> {
				return item.getRowNum() <= size;
			}, (item) -> {
				if (size != sheet.getLastRowNum()) {
					throw new IllegalStateException("工作表格探测总行数已变更，行记录访问快速失败！");
				}
				int next = item.getRowNum() + 1;
				Row row = sheet.getRow(next);
				if (row == null) {
					row = sheet.createRow(next);
				}
				item.setRow(row);
				return item;
			});
		} else {
			return Stream.empty();
		}
	}

	/**
	 * 生成表格包裹行记录流
	 * 
	 * @param startIndex 起始行（包括）
	 * @param endIndex   起始行（排除）
	 * @return 数据行流
	 */
	public Stream<TableRow> substream(int startIndex, int endIndex) {
		if (startIndex < 0) {
			startIndex = 0;
		}
		if (startIndex >= endIndex) {
			return Stream.empty();
		}
		Row first = sheet.getRow(startIndex);
		if (first == null) {
			first = sheet.createRow(startIndex);
		}
		final int excludeLastIndex = endIndex;
		return Stream.iterate(createTableRow(first), (item) -> {
			return item.getRowNum() < excludeLastIndex;
		}, (item) -> {
			int next = item.getRowNum() + 1;
			Row row = sheet.getRow(next);
			if (row == null) {
				row = sheet.createRow(next);
			}
			item.setRow(row);
			return item;
		});
	}

	public TableRow getTableRow(int rownum, boolean autoCreate) {
		Row row = sheet.getRow(rownum);
		if (row == null) {
			if (!autoCreate) {
				throw new ArrayIndexOutOfBoundsException("Sheet页中的数据行已不存在 - " + rownum);
			}
			row = sheet.createRow(rownum);
		}
		return createTableRow(row);
	}
}
